package com.avalon.core.select;

import com.avalon.core.alias.AbstractAliasSupport;
import com.avalon.core.alias.IAliasSupport;
import com.avalon.core.field.*;
import com.avalon.core.select.builder.SelectBuilder;
import com.avalon.core.service.AbstractService;
import com.avalon.core.util.FieldUtils;
import com.avalon.core.util.ObjectUtils;
import com.avalon.core.util.StringUtils;

import java.util.List;

/**
 * 同一级字段分组 包括查询字段 查询条件 排序字段
 */
public class TableFieldSection implements IAliasSupport {
    public Integer getJoinCount() {
        return joinCount;
    }

    private Integer joinCount;//.的个数

    public String getTableName() {
        return tableName;
    }

    private String tableName;//表名 第一个表名.第二个表名.第三个表名
    private SelectionFieldList selectionFieldList;// 查询字段
    private ConditionFieldList conditionFieldList;// 查询条件
    private OrderFieldList orderFieldList;// 排序字段
    private AbstractService service;
    private String alias;//最外层别名

    public TableFieldSection(AbstractService service) {
        setService(service);
    }


    public SelectionFieldList getSelectionFieldList() {
        return selectionFieldList;
    }

    protected void setSelectionFieldList(SelectionFieldList selectionFieldList) {
        this.selectionFieldList = selectionFieldList;
    }

    public ConditionFieldList getConditionFieldList() {
        return conditionFieldList;
    }

    protected void setConditionFieldList(ConditionFieldList conditionFieldList) {
        this.conditionFieldList = conditionFieldList;
    }

    public OrderFieldList getOrderFieldList() {
        return orderFieldList;
    }

    protected void setOrderFieldList(OrderFieldList orderFieldList) {
        this.orderFieldList = orderFieldList;
    }

    public AbstractService getService() {
        return service;
    }

    protected void setService(AbstractService service) {
        this.service = service;
    }


    @Override
    public String getAlias(AbstractAliasSupport abstractAliasSupport) {
        if (StringUtils.isNotEmpty(alias)) {
            return alias;
        }
        if (joinCount == 0) {
            alias = abstractAliasSupport.getAlias(service);
            return alias;
        }
        alias = abstractAliasSupport.getAlias(this);
        return alias;
    }

    /**
     * 区分字段
     *
     * @param field
     */
    public void addField(String field) {
        if (ObjectUtils.isNull(selectionFieldList)) {
            selectionFieldList = new SelectionFieldList();
            completeTable(field);
        }

        selectionFieldList.addField(field, service);
    }

    /**
     * 识别表名
     *
     * @param field
     */
    private void completeTable(String field) {
        if (ObjectUtils.isNotNull(joinCount)) return;
        joinCount = FieldUtils.getJoinCount(field);
        if (joinCount != 0) {
            tableName = FieldUtils.getJoinTableString(field);
        }
    }

    /**
     * 设置空表名
     *
     * @param tableName
     */
    public void addTable(String tableName) {
        joinCount = FieldUtils.getJoinCount(tableName) + 1;
        this.tableName = tableName;
    }

    public void addOrder(String field, String order) {
        if (ObjectUtils.isNull(orderFieldList)) {
            orderFieldList = new OrderFieldList();
        }
        orderFieldList.addOrder(field, order, service);
    }

    public void addOrder(OrderField orderField) {
        completeTable(orderField.getOriginField());
        if (ObjectUtils.isNull(orderFieldList)) {
            orderFieldList = new OrderFieldList();
        }
        orderFieldList.addOrder(orderField);
    }

    public void addCondition(ConditionField conditionField) {
        completeTable(conditionField.getOriginField());
        if (ObjectUtils.isNull(conditionFieldList)) {
            conditionFieldList = new ConditionFieldList();
        }
        conditionFieldList.addCondition(conditionField);
    }


    /**
     * 判断是否同一级字段
     *
     * @param field
     * @return
     */
    public Boolean isEqual(String field) {

        var fieldJoinCount = FieldUtils.getJoinCount(field);

        if (ObjectUtils.isNull(joinCount)) return false;

        if (joinCount == 0) {
            return this.joinCount.equals(fieldJoinCount);
        }

        if (ObjectUtils.isNull(tableName)) return false;

        return this.joinCount.equals(fieldJoinCount) && this.tableName.equals(FieldUtils.getJoinTableString(field));
    }

    /**
     * 判断当前别名是否属于组中
     *
     * @param alias
     * @param abstractAliasSupport
     * @return
     */
    public Boolean containAlias(String alias, AbstractAliasSupport abstractAliasSupport) {
        String tableAlias = getAlias(abstractAliasSupport);
        return tableAlias.equals(alias);
    }

    public SelectionField getField(String field) {
        if (joinCount == 0) {//主表字段
            field = FieldUtils.getJoinFieldString(field);
        } else {
            field = tableName + FieldUtils.getJoinDivision() + FieldUtils.getJoinFieldString(field);
        }

        for (SelectionField selectionField : selectionFieldList) {
            if (selectionField.originField.equals(field)) {
                return selectionField;
            }
        }
        return null;
    }


    public StringBuilder getFieldSql(AbstractAliasSupport abstractAliasSupport) {
        StringBuilder sql = new StringBuilder();
        if (ObjectUtils.isNull(selectionFieldList)) {
            return sql;
        }
        String alias = getAlias(abstractAliasSupport);
        for (SelectionField selectionField : selectionFieldList) {
            if (!sql.isEmpty()) {
                sql.append(", ");
            }
            sql.append(alias).append(".").append(selectionField.getField().getFieldName());
            sql.append(" AS '").append(alias).append(".").append(selectionField.getField().getFieldName()).append("'");
        }
        return sql;
    }

    /**
     * 获取别名字段
     *
     * @param abstractAliasSupport
     * @return
     */
    public StringBuilder getFieldAliasSql(AbstractAliasSupport abstractAliasSupport) {
        StringBuilder sql = new StringBuilder();
        if (ObjectUtils.isNull(selectionFieldList)) {
            return sql;
        }
        String alias = getAlias(abstractAliasSupport);
        for (SelectionField selectionField : selectionFieldList) {
            sql.append(alias).append(".").append(selectionField.getField().getFieldName());
        }
        return sql;
    }

    public StringBuilder getTableSql(AbstractAliasSupport abstractAliasSupport,
                                     SelectBuilder selectBuilder) {
        StringBuilder sql = new StringBuilder();
        if (joinCount == 0) {
            return sql;
        }
        String alias = getAlias(abstractAliasSupport);
        List<String> tableList = FieldUtils.getJoinStringList(tableName);
        if (tableList.size() == 1) {
            RelationField relationField = (RelationField) service.getField(tableName);
            AbstractService relativeService = service.getServiceBean(relationField.getRelativeServiceName());
            if (relationField instanceof One2manyField || relationField instanceof One2oneField) {
                sql.append(" LEFT JOIN ").append(relativeService.getServiceTableName())
                        .append(" ").append(alias).append(" ON ").append(alias).append(".")
                        .append(FieldUtils.underscoreName(relationField.getRelativeFieldName()))
                        .append(" = ").append(service.getAlias(abstractAliasSupport)).append(".")
                        .append(service.getPrimaryKeyName());
            } else if (relationField instanceof Many2oneField) {
                sql.append(" LEFT JOIN ").append(relativeService.getServiceTableName())
                        .append(" ").append(alias).append(" ON ").append(alias).append(".")
                        .append(relativeService.getPrimaryKeyName())
                        .append(" = ").append(service.getAlias(abstractAliasSupport)).append(".")
                        .append(relationField.getFieldName());
            }
        } else {
            String prefixTable = FieldUtils.getJoinString(tableList, tableList.size() - 2);//上一个表
            String currentTable = tableName;//当前表
            String prefixTableAlias = selectBuilder.getPrefixTableAlias(prefixTable);
            String currentTableAlias;
            if (currentTable.equals(tableName)) {
                currentTableAlias = getAlias(abstractAliasSupport);
            } else {
                currentTableAlias = selectBuilder.getPrefixTableAlias(currentTable);
            }
            RelationField relationPreField = (RelationField) service.getField(prefixTable);
            RelationField relationCurField = (RelationField) service.getField(currentTable);

            AbstractService relativePreService = service.getServiceBean(relationPreField.getRelativeServiceName());
            AbstractService relativeCurService = service.getServiceBean(relationCurField.getRelativeServiceName());
            if (relationCurField instanceof One2manyField || relationCurField instanceof One2oneField) {
                sql.append(" LEFT JOIN ").append(relativeCurService.getServiceTableName())
                        .append(" ").append(currentTableAlias).append(" ON ").append(prefixTableAlias).append(".")
                        .append(relativePreService.getPrimaryKeyName())
                        .append(" = ").append(currentTableAlias).append(".")
                        .append(FieldUtils.underscoreName(relationCurField.getRelativeFieldName()));
            } else if (relationCurField instanceof Many2oneField) {
                sql.append(" LEFT JOIN ").append(relativeCurService.getServiceTableName())
                        .append(" ").append(currentTableAlias).append(" ON ").append(alias).append(".")
                        .append(relativeCurService.getPrimaryKeyName())
                        .append(" = ").append(prefixTableAlias).append(".")
                        .append(relationCurField.getFieldName());
            }
        }
        return sql;
    }
}
